﻿using System;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace MvvmFx.Common.Helpers
{
    public static class TransitionHelper
    {
        #region Fade In/Out

        private const double DEFAULT_FADE_OUT_DURATION = 400;
        private const double DEFAULT_FADE_IN_DURATION = 400;

        /// <summary>
        /// Fade in the specified <see cref="UserControl"/>
        /// </summary>
        /// <param name="fadeIn"></param>
        public static void FadeIn(UserControl fadeIn)
        {
            TimeSpan duration = TimeSpan.FromMilliseconds(DEFAULT_FADE_IN_DURATION);

            Storyboard story =
                new Storyboard
                    {
                        FillBehavior = FillBehavior.HoldEnd
                    };

            AnimationHelper.CreateAnimation(
                story,
                fadeIn,
                "Opacity",
                new DoubleAnimation
                    {
                        Duration = duration,
                        From = 0,
                        To = 1
                    });

            story.Completed += delegate
                                   {
                                       fadeIn.Opacity = 1;
                                   };

            story.Begin();
        }

        /// <summary>
        /// Fade in the specified <see cref="UserControl"/>.  
        /// </summary>
        /// <param name="fadeIn">The control to fade in.</param>
        /// <param name="easingFunction">The easing function applied to the animation.</param>
        public static void FadeIn(UserControl fadeIn, IEasingFunction easingFunction)
        {
            TimeSpan duration = TimeSpan.FromMilliseconds(DEFAULT_FADE_IN_DURATION);

            Storyboard story =
                new Storyboard
                    {
                        FillBehavior = FillBehavior.HoldEnd
                    };

            AnimationHelper.CreateAnimation(
                story,
                fadeIn,
                "Opacity",
                new DoubleAnimation
                    {
                        Duration = duration,
                        From = 0,
                        To = 1,
                    },
               easingFunction);

            story.Completed += delegate
                                   {
                                       fadeIn.Opacity = 1;
                                   };

            story.Begin();
        }


        /// <summary>
        /// Fade the specified control out.  
        /// </summary>
        /// <param name="fadeOut">The control to fade out.</param>
        /// <param name="callback">The callback when the control has completed fading out.</param>
        public static void FadeOut(UserControl fadeOut, EventHandler callback)
        {
            TimeSpan duration = TimeSpan.FromMilliseconds(DEFAULT_FADE_OUT_DURATION);

            Storyboard story = new Storyboard();
            story.FillBehavior = FillBehavior.HoldEnd;

            AnimationHelper.CreateAnimation(
                story,
                fadeOut,
                "Opacity",
                new DoubleAnimation
                    {
                        Duration = duration,
                        From = 1,
                        To = 0
                    });

            story.Completed += delegate
                                   {
                                       fadeOut.Opacity = 0;
                                       callback(null, EventArgs.Empty);
                                   };

            story.Begin();
        }

        /// <summary>
        /// Fade the specified control out.  
        /// </summary>
        /// <param name="fadeOut">The control to fade out.</param>
        /// <param name="easingFunction">The easing function applied to the animation.</param>
        /// <param name="callback">The callback when the control has completed fading out.</param>
        public static void FadeOut(UserControl fadeOut, IEasingFunction easingFunction, EventHandler callback)
        {
            TimeSpan duration = TimeSpan.FromMilliseconds(DEFAULT_FADE_OUT_DURATION);

            Storyboard story =
                new Storyboard
                    {
                        FillBehavior = FillBehavior.HoldEnd
                    };

            AnimationHelper.CreateAnimation(
                story,
                fadeOut,
                "Opacity",
                new DoubleAnimation
                {
                    Duration = duration,
                    From = 1,
                    To = 0,
                },
                easingFunction);

            story.Completed += delegate
            {
                fadeOut.Opacity = 0;
                callback(null, EventArgs.Empty);
            };

            story.Begin();
        }


        #endregion

        #region Slide

        /// <summary>
        /// The default slide duration applied.
        /// </summary>
        private const double DEFAULT_SLIDE_DURATION = 600;

        /// <summary>
        /// Slide to <see cref="UserControl"/> to the specified left position.
        /// </summary>
        /// <param name="control">The control to slide.</param>
        /// <param name="to">The left position to slide to.</param>
        public static void Slide(UserControl control, double to)
        {
            control.Visibility = System.Windows.Visibility.Visible;

            TimeSpan duration = TimeSpan.FromMilliseconds(DEFAULT_SLIDE_DURATION);

            Storyboard story =
                new Storyboard
                    {
                        FillBehavior = FillBehavior.HoldEnd
                    };

            //Create the animation.
            //
            AnimationHelper.CreateAnimation(
                story,
                control,
                "(Canvas.Left)",
                new DoubleAnimation
                    {
                        Duration = duration,
                        To = to,
                    });

            story.Completed +=
                delegate
                {
                    Canvas.SetLeft(control, to);
                };

            story.Begin();
        }


        /// <summary>
        /// Slide to <see cref="UserControl"/> to the specified left position.
        /// </summary>
        /// <param name="control">The control to slide.</param>
        /// <param name="easingFunction">The easing function applied to the animation.</param>
        /// <param name="to">The left position to slide to.</param>
        public static void Slide(UserControl control, IEasingFunction easingFunction, double to)
        {
            control.Visibility = System.Windows.Visibility.Visible;

            TimeSpan duration = TimeSpan.FromMilliseconds(DEFAULT_SLIDE_DURATION);

            Storyboard story = new Storyboard { FillBehavior = FillBehavior.HoldEnd };

            //Create the animation.
            //
            AnimationHelper.CreateAnimation(
                story,
                control,
                "(Canvas.Left)",
                new DoubleAnimation
                {
                    Duration = duration,
                    To = to,
                }, easingFunction);

            story.Completed +=
                delegate
                {
                    Canvas.SetLeft(control, to);
                };

            story.Begin();
        }

        #endregion
    }
}